package cn.pomit.springbootwork.oauthauth.config;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;

import cn.pomit.springbootwork.oauthauth.domain.OauthClientInfo;
import cn.pomit.springbootwork.oauthauth.service.OauthClientService;

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
	@Autowired
	@Qualifier("authorizationCodeServices")
	private AuthorizationCodeServices authorizationCodeServices;

	@Autowired
	OauthClientService oauthClientService;

	@Bean
	public PasswordEncoder noOpPasswordEncoder() {
		return NoOpPasswordEncoder.getInstance();
	}

	/**
	 * 可以在这里将客户端数据替换成数据库配置。
	 * 
	 * @return
	 */
	@Bean
	public ClientDetailsService clientDetailsService() {
		InMemoryClientDetailsService inMemoryClientDetailsService = new InMemoryClientDetailsService();
		Map<String, ClientDetails> clientDetailsStore = new HashMap<>();

		List<OauthClientInfo> clientList = oauthClientService.findAll();
		for (OauthClientInfo item : clientList) {
			BaseClientDetails baseClientDetails = new BaseClientDetails();
			baseClientDetails.setClientId(item.getClientId());
			baseClientDetails.setClientSecret(item.getClientSecret());
			baseClientDetails.setAccessTokenValiditySeconds(item.getAccessTokenTime());
			baseClientDetails.setRefreshTokenValiditySeconds(item.getRefreshTokenTime());

			Set<String> salesWords = new HashSet<String>(Arrays.asList(item.getRedirectUrls().split(",")));
			baseClientDetails.setRegisteredRedirectUri(salesWords);
			List<String> scope = Arrays.asList(item.getScopes().split(","));
			baseClientDetails.setScope(scope);

			List<String> authorizedGrantTypes = Arrays.asList(item.getAuthorizedGrantTypes().split(","));
			baseClientDetails.setAuthorizedGrantTypes(authorizedGrantTypes);
			clientDetailsStore.put(item.getClientId(), baseClientDetails);
		}

		inMemoryClientDetailsService.setClientDetailsStore(clientDetailsStore);

		return inMemoryClientDetailsService;
	}

	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		clients.withClientDetails(clientDetailsService());
	}

	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		endpoints.authorizationCodeServices(authorizationCodeServices);
	}

	@Override
	public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
		oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("permitAll()").allowFormAuthenticationForClients();
	}
}
